home *** CD-ROM | disk | FTP | other *** search
/ SunSoft Catalyst CDWARE 1996 May to August / Catalyst CDWARE 1996 May to August.iso / .products / .bin / httpd / src / rfc931.c < prev    next >
C/C++ Source or Header  |  1995-05-18  |  5KB  |  197 lines

  1.  /*
  2.   * rfc931() speaks a common subset of the RFC 931, AUTH, TAP and IDENT
  3.   * protocols. The code queries an RFC 931 etc. compatible daemon on a remote
  4.   * host to look up the owner of a connection. The information should not be
  5.   * used for authentication purposes. This routine intercepts alarm signals.
  6.   * 
  7.   * Diagnostics are reported through syslog(3).
  8.   * 
  9.   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  10.   */
  11.  
  12. #ifndef lint
  13. static char sccsid[] = "@(#) rfc931.c 1.8 93/12/13 22:23:20";
  14. #endif
  15.  
  16. #ifndef _HPUX_SOURCE
  17. #define _HPUX_SOURCE
  18. #endif
  19.  
  20. #ifdef SCO3
  21. #define SIGALRM 14
  22. #endif
  23.  
  24. /* System libraries. */
  25.  
  26. #include <stdio.h>
  27. #ifndef ATTSVR3
  28. #include <syslog.h>
  29. #else
  30. #define syslog(a,b) perror(b)
  31. #endif
  32. #include <sys/types.h>
  33. #include <sys/socket.h>
  34. #include <netinet/in.h>
  35. #include <setjmp.h>
  36. #include <signal.h>
  37.  
  38. extern char *strchr();
  39. extern char *inet_ntoa();
  40.  
  41. /* Local stuff. */
  42.  
  43. /* #include "log_tcp.h" */
  44.  
  45. #define RFC931_TIMEOUT    500
  46. #define    RFC931_PORT    113        /* Semi-well-known port */
  47. #define    ANY_PORT    0        /* Any old port will do */
  48. #define FROM_UNKNOWN  "unknown"
  49.  
  50. int     rfc931_timeout = RFC931_TIMEOUT;/* Global so it can be changed */
  51.  
  52. static jmp_buf timebuf;
  53.  
  54. /* fsocket - open stdio stream on top of socket */
  55.  
  56. static FILE *fsocket(domain, type, protocol)
  57. int     domain;
  58. int     type;
  59. int     protocol;
  60. {
  61.     int     s;
  62.     FILE   *fp;
  63.  
  64.     if ((s = socket(domain, type, protocol)) < 0) {
  65.     syslog(LOG_ERR, "socket: %m");
  66.     return (0);
  67.     } else {
  68.     if ((fp = fdopen(s, "r+")) == 0) {
  69.         syslog(LOG_ERR, "fdopen: %m");
  70.         close(s);
  71.     }
  72.     return (fp);
  73.     }
  74. }
  75.  
  76. /* bind_connect - bind both ends of a socket */
  77.  
  78. int     bind_connect(s, local, remote, length)
  79. int     s;
  80. struct sockaddr *local;
  81. struct sockaddr *remote;
  82. int     length;
  83. {
  84.     if (bind(s, local, length) < 0) {
  85.     syslog(LOG_ERR, "bind: %m");
  86.     return (-1);
  87.     } else {
  88.     return (connect(s, remote, length));
  89.     }
  90. }
  91.  
  92. /* timeout - handle timeouts */
  93.  
  94. static void timeout(sig)
  95. int     sig;
  96. {
  97.     longjmp(timebuf, sig);
  98. }
  99.  
  100. /* rfc931 - return remote user name, given socket structures */
  101.  
  102. char   *rfc931(rmt_sin, our_sin)
  103. struct sockaddr_in *rmt_sin;
  104. struct sockaddr_in *our_sin;
  105. {
  106.     unsigned rmt_port;
  107.     unsigned our_port;
  108.     struct sockaddr_in rmt_query_sin;
  109.     struct sockaddr_in our_query_sin;
  110.     static char user[256];        /* XXX */
  111.     char    buffer[512];        /* XXX */
  112.     char   *cp;
  113.     char   *result = FROM_UNKNOWN;    /* XXX */
  114.     FILE   *fp;
  115.  
  116.     /*
  117.      * Use one unbuffered stdio stream for writing to and for reading from
  118.      * the RFC931 etc. server. This is done because of a bug in the SunOS
  119.      * 4.1.x stdio library. The bug may live in other stdio implementations,
  120.      * too. When we use a single, buffered, bidirectional stdio stream ("r+"
  121.      * or "w+" mode) we read our own output. Such behaviour would make sense
  122.      * with resources that support random-access operations, but not with
  123.      * sockets.
  124.      */
  125.  
  126.     if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
  127.     setbuf(fp, (char *) 0);
  128.  
  129.     /*
  130.      * Set up a timer so we won't get stuck while waiting for the server.
  131.      */
  132.  
  133.     if (setjmp(timebuf) == 0) {
  134.         signal(SIGALRM, timeout);
  135.         alarm(rfc931_timeout);
  136.  
  137.         /*
  138.          * Bind the local and remote ends of the query socket to the same
  139.          * IP addresses as the connection under investigation. We go
  140.          * through all this trouble because the local or remote system
  141.          * might have more than one network address. The RFC931 etc.
  142.          * client sends only port numbers; the server takes the IP
  143.          * addresses from the query socket.
  144.          */
  145.  
  146.         our_query_sin = *our_sin;
  147.         our_query_sin.sin_port = htons(ANY_PORT);
  148.         rmt_query_sin = *rmt_sin;
  149.         rmt_query_sin.sin_port = htons(RFC931_PORT);
  150.  
  151.         if (bind_connect(fileno(fp),
  152.                  (struct sockaddr *) & our_query_sin,
  153.                  (struct sockaddr *) & rmt_query_sin,
  154.                  sizeof(our_query_sin)) >= 0) {
  155.  
  156.         /*
  157.          * Send query to server. Neglect the risk that a 13-byte
  158.          * write would have to be fragmented by the local system and
  159.          * cause trouble with buggy System V stdio libraries.
  160.          */
  161.  
  162.         fprintf(fp, "%u,%u\r\n",
  163.             ntohs(rmt_sin->sin_port),
  164.             ntohs(our_sin->sin_port));
  165.         fflush(fp);
  166.  
  167.         /*
  168.          * Read response from server. Use fgets()/sscanf() so we can
  169.          * work around System V stdio libraries that incorrectly
  170.          * assume EOF when a read from a socket returns less than
  171.          * requested.
  172.          */
  173.  
  174.         if (fgets(buffer, sizeof(buffer), fp) != 0
  175.             && ferror(fp) == 0 && feof(fp) == 0
  176.             && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
  177.                   &rmt_port, &our_port, user) == 3
  178.             && ntohs(rmt_sin->sin_port) == rmt_port
  179.             && ntohs(our_sin->sin_port) == our_port) {
  180.  
  181.             /*
  182.              * Strip trailing carriage return. It is part of the
  183.              * protocol, not part of the data.
  184.              */
  185.  
  186.             if (cp = strchr(user, '\r'))
  187.             *cp = 0;
  188.             result = user;
  189.         }
  190.         }
  191.         alarm(0);
  192.     }
  193.     fclose(fp);
  194.     }
  195.     return (result);
  196. }
  197.